package org.theSeed.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.theSeed.base.pojo.constant.SysConstant;
import org.theSeed.base.pojo.dto.CommonKeyValue;
import org.theSeed.base.utils.SeedStringUtil;
import org.theSeed.mapper.SysResourceMapper;
import org.theSeed.pojo.dto.SysResourceAndRoleCode;
import org.theSeed.pojo.po.SysResource;
import org.theSeed.pojo.ro.EditResourceRo;
import org.theSeed.rbacBaseCommon.pojo.constant.RbacConstant;
import org.theSeed.rbacBaseCommon.pojo.dto.CacheResourceInfoDto;
import org.theSeed.rbacBaseCommon.pojo.sysEnum.ResourceTypeEnum;
import org.theSeed.redisIntegration.utils.RedisUtil;
import org.theSeed.service.SysResourceService;

import java.util.List;

@Service
public class SysResourceServiceImpl implements SysResourceService {
    @Autowired
    private SysResourceMapper sysResourceMapper;

    @Override
    public List<SysResource> listResource() {
        return sysResourceMapper.selectList(Wrappers.lambdaQuery());
    }

    @Override
    public SysResource getResourceDetail(String id) {
        return sysResourceMapper.selectById(id);
    }

    @Override
    @Transactional
    public void editResource(EditResourceRo editResourceRo) {
        RLock lock = RedisUtil.getRedissonClient().getLock(RbacConstant.PERMISSION_UPDATE_PREFIX + SysConstant.SEED);
        if (lock.tryLock()) {
            try {
                SysResource sysResource = BeanUtil.copyProperties(editResourceRo, SysResource.class);
                sysResource.setEnableFlag(SysConstant.Y);
                if (ObjectUtil.isNotEmpty(editResourceRo.getId())){
                    sysResourceMapper.updateById(sysResource);
                    sysResource = sysResourceMapper.selectById(sysResource.getId());
                }else{
                    sysResourceMapper.insert(sysResource);
                }

                //缓存刷新
                if (ObjectUtil.isNotNull(sysResource)){
                    List<SysResourceAndRoleCode> resourceRoleByResourceCode = sysResourceMapper.findResourceRoleByResourceId(sysResource.getResourceCode());
                    if (CollectionUtil.isNotEmpty(resourceRoleByResourceCode)){
                        resourceRoleByResourceCode.stream()
                                .forEach(item->{
                                    String roleResourcePermissionKey = RbacConstant.RESOURCE_PERMISSION_KEY_PREFIX + item.getRoleCode();
                                    String roleApiPermissionKey = RbacConstant.API_PERMISSION_KEY_PREFIX + item.getRoleCode();
                                    if (ResourceTypeEnum.isMenu(item.getResourceType())) {
                                        RedisUtil.getRedissonClient().getMap(roleResourcePermissionKey).put(item.getResourceCode(), item.getResourceCode());
                                    } else {
                                        RedisUtil.getRedissonClient().getMap(roleApiPermissionKey).put(SeedStringUtil.concatStr(item.getParentCode(),":",item.getResourceCode()), item.getResourceCode());
                                    }
                                });
                    }
                }
            }finally {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional
    public void enableResource(CommonKeyValue<String, String> enableRo) {
        RLock lock = RedisUtil.getRedissonClient().getLock(RbacConstant.PERMISSION_UPDATE_PREFIX + SysConstant.SEED);
        if (lock.tryLock()) {
            try {
                SysResource sysResource = new SysResource();
                sysResource.setId(enableRo.getKey());
                sysResource.setEnableFlag(enableRo.getValue());
                sysResourceMapper.updateById(sysResource);

                //缓存刷新
                if (ObjectUtil.isNotNull(sysResource)){
                    List<SysResourceAndRoleCode> resourceRoleByResourceCode = sysResourceMapper.findResourceRoleByResourceId(sysResource.getId());
                    if (CollectionUtil.isNotEmpty(resourceRoleByResourceCode)){
                        resourceRoleByResourceCode.stream()
                                .forEach(item->{
                                    String roleResourcePermissionKey = RbacConstant.RESOURCE_PERMISSION_KEY_PREFIX + item.getRoleCode();
                                    String roleApiPermissionKey = RbacConstant.API_PERMISSION_KEY_PREFIX + item.getRoleCode();
                                    if (ResourceTypeEnum.isMenu(item.getResourceType())) {
                                        RedisUtil.getRedissonClient().getMap(roleResourcePermissionKey).put(item.getResourceCode(), item.getResourceCode());
                                    } else {
                                        RedisUtil.getRedissonClient().getMap(roleApiPermissionKey).put(SeedStringUtil.concatStr(item.getParentCode(),":",item.getResourceCode()), item.getResourceCode());
                                    }
                                });
                    }
                }
            }finally {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional
    public void deleteResource(String id) {
        RLock lock = RedisUtil.getRedissonClient().getLock(RbacConstant.PERMISSION_UPDATE_PREFIX + SysConstant.SEED);
        if (lock.tryLock()) {
            try {
                SysResource tmpResource = sysResourceMapper.selectById(id);
                if (ObjectUtil.isNotNull(tmpResource)){
                    sysResourceMapper.deleteById(id);
                    //缓存刷新
                    if (ObjectUtil.isNotNull(tmpResource)){
                        List<SysResourceAndRoleCode> resourceRoleByResourceCode = sysResourceMapper.findResourceRoleByResourceId(tmpResource.getId());
                        if (CollectionUtil.isNotEmpty(resourceRoleByResourceCode)){
                            resourceRoleByResourceCode.stream()
                                    .forEach(item->{
                                        String roleResourcePermissionKey = RbacConstant.RESOURCE_PERMISSION_KEY_PREFIX + item.getRoleCode();
                                        String roleApiPermissionKey = RbacConstant.API_PERMISSION_KEY_PREFIX + item.getRoleCode();
                                        if (ResourceTypeEnum.isMenu(item.getResourceType())) {
                                            RedisUtil.getRedissonClient().getMap(roleResourcePermissionKey).put(item.getResourceCode(), item.getResourceCode());
                                        } else {
                                            RedisUtil.getRedissonClient().getMap(roleApiPermissionKey).put(SeedStringUtil.concatStr(item.getParentCode(),":",item.getResourceCode()), item.getResourceCode());
                                        }
                                    });
                        }
                    }
                }
            }finally {
                lock.unlock();
            }
        }
    }
}
